package com.zbkj.crmeb.order.pprocess;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.constants.WeChatConstants;
import com.crmeb.core.exception.CrmebException;
import com.taobao.pac.sdk.cp.dataobject.response.MODUAN_ORDER_CREATE.response;
import com.utils.DateUtil;
import com.utils.LLianPayDateUtils;
import com.utils.adapay.degree.SimpleHttpsClient;
import com.utils.lianlianpay.client.LLianPayClient;
import com.utils.lianlianpay.config.LLianPayConstant;
import com.utils.lianlianpay.dto.confirm.*;
import com.utils.lianlianpay.dto.refund.*;
import com.utils.monitor.DingMsgEnum;
import com.utils.monitor.DingTalkMsgUtil;
import com.utils.query.QueryCityItem;
import com.zbkj.crmeb.chant.request.PurchaseProductRequest;
import com.zbkj.crmeb.enums.RoleEnum;
import com.zbkj.crmeb.finance.model.UserRecharge;
import com.zbkj.crmeb.finance.service.UserRechargeService;
import com.zbkj.crmeb.finance.service.process.IRechargeOrderProcess;
import com.zbkj.crmeb.front.request.*;
import com.zbkj.crmeb.front.response.CustomsPushPayResponse;
import com.zbkj.crmeb.front.response.LianlianOrderResponse;
import com.zbkj.crmeb.front.response.LianlianPayResponse;
import com.zbkj.crmeb.front.response.OrderPayResponse;
import com.zbkj.crmeb.front.vo.CityItemVo;
import com.zbkj.crmeb.front.vo.ProvinceCityItemVo;
import com.zbkj.crmeb.merchant.api.request.BuyMemberRequest;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.request.StoreOrderRefundRequest;
import com.zbkj.crmeb.store.service.StoreOrderInfoService;
import com.zbkj.crmeb.store.service.StoreOrderService;
import com.zbkj.crmeb.store.vo.StoreOrderInfoVo;
import com.zbkj.crmeb.system.service.SystemConfigService;
import com.zbkj.crmeb.system.service.SystemGroupDataService;
import com.zbkj.crmeb.system.vo.SystemGroupDataRechargeConfigVo;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.service.UserService;

/**
 * 连连聚合支付
 * @author daigb
 * @date:  2022-07-18 11:31
 */
@Slf4j
@Service("lianlianDegreePayOrderProcess")
public class LianlianDegreePayOrderProcess extends AbstractOrangePayOrderProcess implements IRechargeOrderProcess {
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private SimpleHttpsClient simpleHttpsClient;
    @Autowired
    private UserService userService;
    @Autowired
    private SystemGroupDataService systemGroupDataService;
    @Autowired
    private UserRechargeService userRechargeService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    
//    @Value("${lianlian.degree.payUrl}")
    private String payUrl;
//    @Value("${lianlian.degree.refundUrl}")
    private String refundUrl;
	//    @Value("${lianlian.degree.customsUrl}")
    private String customsUrl;
	//    @Value("${lianlian.degree.transDivUrl}")
    private String transDivUrl;
	//    @Value("${lianlian.degree.rollbackUrl}")
    private String rollbackUrl;
	//    @Value("${lianlian.degree.password}")
	private String password;
	//   @Value("${lianlian.degree.alias}")
	private String alias;
	//	@Value("${lianlian.suyun.merIds}")
	private List<Integer> syMerIds;
	//	@Value("${lianlian.chengpin.merIds}")
	private List<Integer> cpMerIds;
	//@Value("${lianlian.chutai.merIds}")
	private List<Integer> ctMerIds;
	//@Value("${lianlian.maisi.merIds}")
	private List<Integer> msMerIds;
	//@Value(("${lianlian.wenmiaojie.merIds}"))
	private List<Integer> wmjMerIds;
	//@Value("${productType.merchantId}")
	private Integer productTypeMerchantId;

	/**
	 * 连接超时 毫秒
	 */
	private static final Integer CONNECT_TIME_OUT = 5000;
	/**
	 * 响应超时 毫秒
	 */
	private static final Integer RESP_TIME_OUT = 30000;

	private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    
    public static final String PATH = "/data/cert/adapay/"; // TODO lianlian
    public static final String CHARSET = "1";
    public static final String VERSION = "3.0";
    public static final String LANGUAGE = "1";
    public static final String SIGN_TYPE = "4";

    // 诚品
    public static final String MERCHANT_ACCT_ID_CP = "10122070636";
    public static final String TERMINAL_ID_CP = "CPRS001";
    public static final String TERMINAL_CUSTOMS_ID_CP = "CPRS006";
    
    // 速云
    public static final String MERCHANT_ACCT_ID_SY = "10122080652";
    public static final String TERMINAL_ID_SY = "SYGYL001";
//    public static final String TERMINAL_CUSTOMS_ID_SY = "SYGYL007";

	public static final String TERMINAL_CUSTOMS_ID_SY = "SYGYL008";
	public static final String TERMINAL_CUSTOMS_ID_WMJ = "SYGYL006";

	// 初苔
	public static final String MERCHANT_ACCT_ID_CT = "10123020695";
	public static final String TERMINAL_ID_CT = "WZCT001";
	public static final String TERMINAL_CUSTOMS_ID_CT = "WZCT002";

	// 麦丝
	public static final String MERCHANT_ACCT_ID_MS = "10123050712";
	public static final String TERMINAL_ID_MS = "MSMJ001";
	public static final String TERMINAL_CUSTOMS_ID_MS = "MSMJ002";
    
    public static final String CURRENCY = "CNY";
	public static final String SIGNATUREPARAMS = "competCustom,customCode,customVersion,dealId,declareId,"
			+ "decResult,ecpDomainName,ecpShortName,errorCode,errorMsg,freightAmt,goodsAmt,iaqInstCode,"
			+ "merchantAcctId,merCustomCode,merCustomName,offsetAmt,orderAmt,orderCurrency,orderId,payerIdType,"
			+ "payerIdNumber,payerName,taxAmt,terminalId,bizType,version";


	// 测试环境请求地址
	public static final String ORDER_URL_TEST = "https://accpapi-ste.lianlianpay-inc.com/v1/txn/tradecreate";
	// 测试环境请求地址
	public static final String PAY_URL_TEST = "https://accpapi-ste.lianlianpay-inc.com/v1/txn/payment-gw";
	// 测试环境请求地址
	public static final String REFUND_URL_TEST = "https://accpapi-ste.lianlianpay-inc.com/v1/txn/more-payee-refund";

	// 测试环境商户号
	public static final String OID_PARTNER_TEST = "2020042200284052";

	/**
     * 创建订单
     */
    public OrderPayResponse creatPayOrder(String key, OrderCreateRequest orderRequest, String ip) {
		log.info("连连支付创建支付单：{},{},{}", key, JSONObject.toJSONString(orderRequest), ip);
		// 创建订单数据
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        StoreOrder storeOrder = super.createOrder(key, orderRequest, ip);
        orderPayResponse.setStatus(Constants.LIANLIAN_DEGREE_PAY);
		orderPayResponse.addExtend("orderId",storeOrder.getOrderId());
        // 统一支付创单
		Map<String, Object> result = unifyCreateOrder(storeOrder, ip, Constants.SERVICE_PAY_TYPE_ORDER);
		// 连连支付网关类支付
		Map<String,Object> payMap = payPayment(storeOrder, ip, Constants.SERVICE_PAY_TYPE_ORDER);
		if(null != payMap.get("appid")) {
			result.put("appid", payMap.get("appid").toString());
		}
		if(null != payMap.get("token")) {
			result.put("token", payMap.get("token").toString());
		}
        result.put("orderId", storeOrder.getOrderId());
        orderPayResponse.setResult(result);
		final Integer orderAutoId = orderRequest.getOrderAutoId();
		// TODO 下单成功异步触发支付单申报
//		if (Objects.equals(result.get("result"),"SUCCESS")){
//			CompletableFuture.runAsync(()->{
//				StoreOrder order = storeOrderService.getById(orderAutoId);
//				List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, orderAutoId));
//				if (CollectionUtils.isEmpty(list)){
//					return;
//				}
//				List<Integer> orderInfoIds = list.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
//				String pushResult = "";
//				try {
//					Thread.sleep(30*1000);
//					// TODO DIDIOK 支付22
//					pushResult = storeOrderService.pushLianlianCustoms(orderInfoIds);
//				}catch (Exception e){
//					pushResult = e.getCause()+e.getMessage();
//					log.error("自动推送支付单失败:",e);
//				}
//				DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,String.format("支付单自动申报结果:%S,%s",order.getOrderId(),pushResult));
//			});
//		}
        return orderPayResponse;
    }

	/**
	 * 连连支付海关推单
	 */
	@Override
	public Map<String, Object> toPayOrder(StoreOrder storeOrder, String ip) {
		log.info("支付：连连支付海关推单 toPayOrder：{},{}", JSONObject.toJSONString(storeOrder), ip);
//		//支付调用请求
		Map<String, Object> resultMap = new HashMap<>();
//		Map<String, Object> result = payPayment(order, ip, Constants.SERVICE_PAY_TYPE_ORDER);
//
		resultMap.put("orderId", storeOrder.getOrderId());
		resultMap.put("orderStatus", storeOrder.getStatus());
		resultMap.put("status", Constants.LIANLIAN_DEGREE_PAY);

		// 下单成功异步触发支付单申报
		CompletableFuture.runAsync(()->{
			List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, storeOrder.getId()));
			if (CollectionUtils.isEmpty(list)){
				return;
			}
			List<Integer> orderInfoIds = list.stream().map(StoreOrderInfo::getId).collect(Collectors.toList());
			String pushResult = "";
			try {
				Thread.sleep(30*1000);
				pushResult = storeOrderService.pushLianlianCustoms(orderInfoIds);
			}catch (Exception e){
				pushResult = e.getCause()+e.getMessage();
				log.error("自动推送支付单失败（连连）:",e);
			}
			DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,String.format("支付单自动申报结果（连连）:%S,%s",storeOrder.getOrderId(),pushResult));
		});

		return resultMap;
	}

    /**
     * 退款
     */
    @Override
    public boolean refund(StoreOrderRefundRequest request, StoreOrder storeOrder, StoreOrderInfo storeOrderInfo) {
		log.info("连连支付退款 request ：{}, storeOrder:{}, storeOrderInfo:{}", JSONObject.toJSONString(request), JSONObject.toJSONString(storeOrder), JSONObject.toJSONString(storeOrderInfo));
		Integer merId = storeOrder.getMerId();
    	// 直接退款情况
        if(null == request.getAmount() || request.getAmount().compareTo(BigDecimal.ZERO)==0){
            return goOnRefund(request, storeOrder, storeOrderInfo);
        }
        // 退货退款情况, 先进行分账回退
//        if(1 == request.getType() && StringUtil.isNotBlank(storeOrder.getTransBackParam()) && MER_ID != merId) {
//        	JSONObject transBackParam = JSONObject.parseObject(storeOrder.getTransBackParam());
//        	String requestId = transBackParam.getString("requestId");
//        	String price = transBackParam.getString("ext1");
//        	
//        	boolean transDivRollbackStatus = transDivRollback(requestId, Constants.HF_USER_ID, price, merId);
//        	if(!transDivRollbackStatus) {
//        		throw new CrmebException("退款前分账回退失败! 请联系技术人员!");
//        	}
//        }
        
        // 回调地址
        String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
        // 组装参数
		MorePayeeRefundParams params = getBasicRefundParams(request, storeOrder, storeOrderInfo);

		params.setNotify_url(domain + WeChatConstants.PAY_NOTIFY_API_URI_LIANLIAN_DEGREE_REFUND);

		log.info("--------------- 连连聚合支付退款原始数据: {}", JSON.toJSONString(params));
		LLianPayClient lLianPayClient = new LLianPayClient();
		String resultJsonStr = lLianPayClient.sendRequest(Constants.REFUND_URL_PROD, JSON.toJSONString(params));
		MorePayeeRefundResult morePayeeRefundResult = JSON.parseObject(resultJsonStr, MorePayeeRefundResult.class);
//
		log.info("--------------- 连连聚合支付退款返回结果源数据: {}", JSON.toJSONString(morePayeeRefundResult));

		String ret_code = morePayeeRefundResult.getRet_code();
		String ret_msg = morePayeeRefundResult.getRet_msg();
		String oid_partner = morePayeeRefundResult.getOid_partner();
		String user_id = morePayeeRefundResult.getUser_id();
		BigDecimal total_amount = morePayeeRefundResult.getTotal_amount();
		String txn_seqno = morePayeeRefundResult.getTxn_seqno();
		String accp_txno = morePayeeRefundResult.getAccp_txno();


//		if ("C0".equals(refundResult)) {
//			return goOnRefund(request, storeOrder,storeOrderInfo);
//		}
		// 结果处理(不代表实际退款成功)
        if ("0000".equals(ret_code)) {
			log.info("--------------- 连连聚合支付退款成功!: {}", JSON.toJSONString(morePayeeRefundResult));
			return goOnRefund(request, storeOrder,storeOrderInfo);
        } else {
			log.error("--------------- 连连聚合支付退款失败!: {}", JSON.toJSONString(morePayeeRefundResult));
        	storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(),storeOrderInfo.getChildOrderNumber(), request.getAmount(), "失败,错误信息:" + ret_msg, request.getType() == 1);
            throw new CrmebException(ret_msg);
        }
    }

	/**
	 * 组装参数
	 * @return
	 */
	private MorePayeeRefundParams getBasicRefundParams(StoreOrderRefundRequest request, StoreOrder storeOrder, StoreOrderInfo storeOrderInfo) {

		MorePayeeRefundParams params = new MorePayeeRefundParams();
		String timestamp = LLianPayDateUtils.getTimestamp();
		params.setTimestamp(timestamp);
		// TODO OID_PARTNER_TEST
		params.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
		// 原交易付款方user_id
		params.setUser_id(storeOrder.getUid() == null ? null : String.valueOf(storeOrder.getUid()));

		LocalDateTime time = LocalDateTime.now();
		// 原商户订单信息
		OriginalOrderInfo originalOrderInfo = new OriginalOrderInfo();
		// 原支付交易商户系统唯一交易流水号
		originalOrderInfo.setTxn_seqno(storeOrder.getOrderId());
		// 订单总金额
		originalOrderInfo.setTotal_amount(storeOrder.getPayPrice());
		params.setOriginalOrderInfo(originalOrderInfo);

		// 退款订单信息
		RefundOrderInfo refundOrderInfo = new RefundOrderInfo();
		// 退款订单号。标识一次退款请求，商户系统需要保证唯一
		refundOrderInfo.setRefund_seqno(storeOrder.getOrderId() + time.getHour() + "" + time.getMinute() + "" + time.getSecond());
		refundOrderInfo.setRefund_time(timestamp);
		// 退款总金额。本次需要退款的金额，不允许超过对应原收款方的收款金额
		refundOrderInfo.setRefund_amount(request.getAmount());
		params.setRefundOrderInfo(refundOrderInfo);

		// 原收款方退款信息
		PyeeRefundInfo pyeeRefundInfo = new PyeeRefundInfo();
		// 原收款方id，本次退款需要处理的原交易收款方id
		pyeeRefundInfo.setPayee_id(Constants.OID_PARTNER_PROD_TUGOU);
        /*
        原收款方类型。
        用户：USER
        平台商户：MERCHANT
         */
		pyeeRefundInfo.setPayee_type("MERCHANT");
        /*
        原收款方账户类型。
        用户账户：USEROWN
        平台商户自有资金账户：MCHOWN
        平台商户担保账户：MCHASSURE
        平台商户优惠券账户：MCHCOUPON
        平台商户手续费账户：MCHFEE
         */
		// TODO 平台商户自有资金账户：MCHOWN
		pyeeRefundInfo.setPayee_accttype("MCHOWN");
		// 退款金额。本次需要退款的金额，不允许超过对应原收款方的收款金额。
		pyeeRefundInfo.setPayee_refund_amount(request.getAmount());
		// 垫资标识。当原收款方金额不足时，是否由平台垫资的标识，默认:N
		pyeeRefundInfo.setIs_advance_pay("N");
		params.setPyeeRefundInfos(Arrays.asList(new PyeeRefundInfo[]{pyeeRefundInfo}));

		// 原付款方式退款规则信息
		RefundMethod refundMethod = new RefundMethod();
		// 付款方式
		refundMethod.setMethod("WECHAT_APP_WXA");
		// 退款金额
		refundMethod.setAmount(request.getAmount());
		params.setRefundMethods(Arrays.asList(new RefundMethod[]{refundMethod}));

		return params;
	}

	/**
     * 购买会员
     */
    @Override
    public Object buyMember(BuyMemberRequest request) {
    	// 虚拟订单对象
        StoreOrder order = new StoreOrder();
        order.setMerId(request.getMerId());
        order.setOrderId(request.getOrderNo());
        order.setUid(request.getUid());
        order.setPayPrice(request.getPrice());
        order.setTotalNum(1);
    	
        //支付调用请求
    	Map<String, Object> resultMap = new HashMap<>();;
        Map<String, Object> result = payPayment(order, request.getClientIp(), Constants.SERVICE_PAY_TYPE_MEMBER);
        result.put("order_id",request.getOrderNo());
        resultMap.put("data", result);
        resultMap.put("status", Constants.LIANLIAN_DEGREE_PAY);
        
        return resultMap;
    }

	@Override
	public Map<String, Object> purchaseProduct(PurchaseProductRequest purchaseProductRequest, String ip) {
		// 虚拟订单
		StoreOrder storeOrder = new StoreOrder();
		storeOrder.setMerId(productTypeMerchantId);
		storeOrder.setOrderId(purchaseProductRequest.getOrderNo());
		storeOrder.setPayPrice(RoleEnum.getEnumByCode(purchaseProductRequest.getProductType()).getPrice());
		storeOrder.setTotalNum(1);
		storeOrder.setPayType(Constants.PAY_TYPE_WE_CHAT_NATIVE);

		// 支付调用请求
		Map<String, Object> resultMap = new HashMap<>();
		Map<String, Object> result = payPayment(storeOrder, ip, Constants.SERVICE_PAY_TYPE_PRODUCT);
		result.put("order_id", purchaseProductRequest.getOrderNo());
		resultMap.put("data", result);
		resultMap.put("status", Constants.LIANLIAN_DEGREE_PAY);

		return resultMap;
	}

	/**
     * 在线充值
     */
    @Override
    public Map<String, Object> rechage(UserRechargeRequest request) {
        request.setPayments(Constants.PAY_TYPE_LIANLIAN_DEGREE);
        // 验证金额是否为最低金额
        BigDecimal rechargeMinAmount = new BigDecimal(systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_RECHARGE_MIN_AMOUNT));
        if(0 < rechargeMinAmount.compareTo(request.getPrice())){
            throw new CrmebException("充值金额不能低于" + rechargeMinAmount);
        }
        // 获取充值模板
        if(request.getGroupDataId() > 0){
            SystemGroupDataRechargeConfigVo systemGroupData = systemGroupDataService.getNormalInfo(request.getGroupDataId(), SystemGroupDataRechargeConfigVo.class);
            if(null == systemGroupData){
                throw new CrmebException("您选择的充值方式已下架");
            }
            //售价和赠送
            request.setPrice(systemGroupData.getPrice());
            request.setGivePrice(systemGroupData.getGiveMoney());
        }
        //生成系统订单
        request.setUserId(userService.getUserIdException());
        UserRecharge userRecharge = userRechargeService.create(request);

    	// 虚拟订单对象
        StoreOrder order = new StoreOrder();
        order.setMerId(request.getMerId());
        order.setOrderId(userRecharge.getOrderId());
        order.setUid(request.getUserId());
        order.setPayPrice(request.getPrice());
        order.setTotalNum(1);
        //支付调用请求
        Map<String, Object> resultMap = new HashMap<>();
    	Map<String, Object> result = payPayment(order, request.getClientIp(), Constants.SERVICE_PAY_TYPE_RECHARGE);
    	resultMap.put("orderId", order.getOrderId());
    	resultMap.put("data", result);
    	resultMap.put("status", Constants.LIANLIAN_DEGREE_PAY);
    	resultMap.put("type", request.getFromType());
        
        return resultMap;
    }

    /**
     * 二维码充值
     */
    @Override
    public UserRecharge createImgRecharge(BigDecimal price) {
        return null;
    }

    /******************************** 以下为工具方法 ******************************/
    /**
     * 统一支付床单
     * @author daigb
     * @date:  2022-07-18 16:01
     */
    private Map<String,Object> unifyCreateOrder(StoreOrder order, String ip, String ex1) {
		log.info("连连支付统一支付创单：{},{},{}", JSONObject.toJSONString(order), ip, ex1);
		Integer merId = order.getMerId();
    	// 基础参数
    	LianlianOrderRequest payRequest = getOrderParams(order, merId);
//    	List<PayeeInfoRequest> payeeInfoRequestList = payRequest.getPayeeInfo();
//		// 收款方类型。 用户：USER 平台商户：MERCHANT
//		PayeeInfoRequest payeeInfoRequest = payeeInfoRequestList.get(0);
//    	payeeInfoRequest.setPayee_type("MERCHANT");
//
//		// 获取商户appId
//		String appId = systemConfigService.getValueByKey("routine_appid_new_" + order.getMerId());
//		if (StringUtils.isBlank(appId)){
//			appId = systemConfigService.getValueByKeyException("routine_appid_" + order.getMerId());
//		}
//
//		// 收款方标识，收款方为用户时，为用户user_id，收款方为平台商户时，取平台商户号。
//		payeeInfoRequest.setPayee_id(appId);
//		String signData = null;
//		// 加签
//		try {
//			signData = md5Encrypt(JSON.toJSONString(payRequest).toLowerCase(),"UTF-8");
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		log.info("--------------- 连连聚合支付下单原数据: {}", JSON.toJSONString(payRequest));
		LLianPayClient lLianPayClient = new LLianPayClient();
		// TODO ORDER_URL_TEST
		String resultJsonStr = lLianPayClient.sendRequest(Constants.ORDER_URL_PROD, JSON.toJSONString(payRequest));
//		String payResult = null;
//		try {
//			payResult = HttpUtils.post(payUrl, JSON.toJSONString(payRequest), RESP_TIME_OUT,CONNECT_TIME_OUT);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		log.info("--------------- 连连聚合支付下单返回结果源数据: {}", JSON.toJSONString(resultJsonStr));

        // TODO 海关清关原始参数保存
        storeOrderService.update(Wrappers.<StoreOrder>lambdaUpdate()
        		.set(StoreOrder :: getPayParam, JSON.toJSONString(payRequest))
        		.eq(StoreOrder :: getOrderId, order.getOrderId())
        		);

		// 下单结果
		LianlianOrderResponse response = JSONObject.parseObject(resultJsonStr, LianlianOrderResponse.class);

		String ret_code = response.getRet_code();
		String ret_msg = response.getRet_msg();
		String oid_partner = response.getOid_partner();
		String user_id = response.getUser_id();
		BigDecimal total_amount = response.getTotal_amount();
		String txn_seqno = response.getTxn_seqno();
		String accp_txno = response.getAccp_txno();


		// 返回结果
		Map<String, Object> result = new HashMap<>();
		if ("0000".equals(ret_code)) {
			log.info("--------------- 连连聚合支付下单成功!: {}", JSON.toJSONString(resultJsonStr));
			result.put("result", "SUCCESS");
		} else {
			result.put("result", ret_msg);
			log.error("--------------- 连连聚合支付下单失败!: {}", JSON.toJSONString(resultJsonStr));
		}
		
		return result;
    }
	/**
	 * 支付下单真实请求
	 * @author daigb
	 * @date:  2022-07-18 16:01
	 */
	private Map<String,Object> payPayment(StoreOrder order, String ip, String ex1) {
		log.info("连连支付网关类支付 payPayment：{},{},{}", JSONObject.toJSONString(order), ip, ex1);
		Integer merId = order.getMerId();
		// 基础参数
		LianlianPayRequest payRequest = getPayParams(order, merId, ip);
//		PayerInfoRequest payerInfoRequest = payRequest.getPayerInfo();
//		// 付款方类型。 用户：USER 平台商户：MERCHANT
//		payerInfoRequest.setPayee_type("USER");
//
//		// 获取商户appId
//		String appId = systemConfigService.getValueByKey("routine_appid_new_" + order.getMerId());
//		if (StringUtils.isBlank(appId)){
//			appId = systemConfigService.getValueByKeyException("routine_appid_" + order.getMerId());
//		}
//
//		// 付款方标识，付款方为用户时，为用户user_id，收款方为平台商户时，取平台商户号。
//		payerInfoRequest.setPayee_id(appId);
//		String signData = null;
//		// 加签
//		try {
//			signData = md5Encrypt(JSON.toJSONString(payRequest).toLowerCase(),"UTF-8");
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		log.info("--------------- 连连聚合支付原数据: {}", JSON.toJSONString(payRequest));
		LLianPayClient lLianPayClient = new LLianPayClient();
		String payResult = lLianPayClient.sendRequest(Constants.PAY_URL_PROD, JSON.toJSONString(payRequest));
//		String payResult = null;
//		try {
//			payResult = HttpUtils.post(PAY_URL_PROD, JSON.toJSONString(payRequest), RESP_TIME_OUT,CONNECT_TIME_OUT);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		log.info("--------------- 连连聚合支付返回结果数据: {}", JSON.toJSONString(payResult));

		// 海关清关原始参数保存  TODO
		storeOrderService.update(Wrappers.<StoreOrder>lambdaUpdate()
				.set(StoreOrder :: getPayParam, JSON.toJSONString(payRequest))
				.eq(StoreOrder :: getOrderId, order.getOrderId())
		);

		// 下单结果
		LianlianPayResponse response = JSONObject.parseObject(payResult, LianlianPayResponse.class);

		String ret_code = response.getRet_code();
		String ret_msg = response.getRet_msg();
		String oid_partner = response.getOid_partner();
		String user_id = response.getUser_id();
		BigDecimal total_amount = response.getTotal_amount();
		String txn_seqno = response.getTxn_seqno();
		String accp_txno = response.getAccp_txno();
		String token = response.getToken();
		String gateway_url = response.getGateway_url();
		String payload = response.getPayload();


		// 返回结果
		Map<String, Object> result = new HashMap<>();
		if ("0000".equals(ret_code)) {
			log.info("--------------- 连连聚合支付成功! payload: {}", JSON.toJSONString(payload));
			JSONObject jsonObject = JSONObject.parseObject(payload);
			if(null != jsonObject) {
				if(null != jsonObject.get("appid")) {
					result.put("appid", jsonObject.get("appid").toString());
				}
				if(null != jsonObject.get("token")) {
					result.put("token", jsonObject.get("token").toString());
				}
			}
			result.put("result", "SUCCESS");
		} else {
			result.put("result", ret_msg);
			log.error("--------------- 连连聚合支付失败!: {}", JSON.toJSONString(payResult));
		}

		return result;
	}

    /**
     * 基础参数组装
     * @author daigb
     * @date:  2022-07-18 15:29
     */
    private LianlianPayRequest getPayParams(StoreOrder order, Integer merId, String ip) {
		log.info("连连支付网关类支付 getPayParams：{},{},{}", JSONObject.toJSONString(order), merId, ip);
		LianlianPayRequest payRequest = new LianlianPayRequest();

		// 回调地址
		// TODO lianlian
		String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
		String domainUrl = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN_URL);

		String timestamp = LLianPayDateUtils.getTimestamp();
		Integer user_id = order.getUid();
		User user = null;
		String userCreateTime = null;
		String userTel = null;
		if(user_id != null) {
			user = userService.getById(order.getUid());
			if(user != null) {
				userCreateTime = DateUtil.dateToStr(user.getCreateTime(), Constants.DATE_TIME_FORMAT_NUM);
				userTel = user.getPhone();
			}
		}

		List<StoreOrderInfoVo> orderInfoList = storeOrderInfoService.getOrderListByOrderId(order.getId());
		if(orderInfoList.size() < 1){
			throw new CrmebException("在订单里没有找到商品数据");
		}
//        return orderList.get(0).getInfo().getJSONObject("productInfo").getString("store_name");
		String goods_name = orderInfoList.get(0).getInfo().getProductInfo().getStoreName();
		Integer goods_count = orderInfoList.stream().mapToInt(e -> e.getNum() == null ? 0 : e.getNum()).sum();

		payRequest.setTimestamp(timestamp);
		payRequest.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
//        String extendParams = "{\"identity\":\"{\"type\":\"IDCARD\",\"number\":\"" + order.getIdCard() + "\",\"name\":\"" + order.getPayName() + "\"}\"}";
		LianlianPayExtendParamsRequest extendParamsRequest = new LianlianPayExtendParamsRequest();
		LianlianPayExtendParamsRequest.ExtendParamsIdentityRequest identityRequest= new LianlianPayExtendParamsRequest.ExtendParamsIdentityRequest();
		identityRequest.setType("IDCARD");
		identityRequest.setName(order.getPayName());
		identityRequest.setNumber(order.getIdCard());
		extendParamsRequest.setIdentity(identityRequest);
		String extendParams = JSONObject.toJSONString(extendParamsRequest);
        payRequest.setExtend_params(extendParams);

		payRequest.setTxn_seqno(order.getOrderId());
		payRequest.setTotal_amount(order.getPayPrice());
//		payRequest.setOpenid(userService.getInfoToken());

		RiskItemRequest riskItemRequest = new RiskItemRequest();
		// 基础类风控参数，原来是4008，连连要求修改
		riskItemRequest.setFrms_ware_category("4016");
		riskItemRequest.setUser_info_mercht_userno(user_id == null ? null : String.valueOf(user_id));
		// TODO 用户绑定手机号
		if(userTel == null){
			userTel = order.getUserPhone();
		}
		if (StringUtils.isNotEmpty(userTel) && userTel.startsWith("0|+86")) {
			userTel = userTel.substring(5).trim();
		}else if (StringUtils.isNotEmpty(userTel) && userTel.startsWith("+86")){
			userTel = userTel.substring(3).trim();
		}
		riskItemRequest.setUser_info_bind_phone(userTel);

		riskItemRequest.setUser_info_dt_register(userCreateTime);
		riskItemRequest.setGoods_name(goods_name);
		// 实物类风控参数
		riskItemRequest.setVirtual_goods_status("0");
//		riskItemRequest.setVirtual_goods_amount();
		riskItemRequest.setGoods_count(String.valueOf(goods_count));
		riskItemRequest.setDelivery_full_name(order.getRealName()); // storeOrder.setRealName(cor.getAddressInfo().getRealName());
		String deliveryPhone = order.getUserPhone();
		if (StringUtils.isNotEmpty(deliveryPhone) && deliveryPhone.startsWith("0|+86")) {
			deliveryPhone = deliveryPhone.substring(5).trim();
		}else if (StringUtils.isNotEmpty(deliveryPhone) && deliveryPhone.startsWith("+86")){
			deliveryPhone = deliveryPhone.substring(3).trim();
		}
		riskItemRequest.setDelivery_phone(deliveryPhone);
		// 物流方式:普通快递。
		riskItemRequest.setLogistics_mode("2");
		// TODO 发货时间: other - 72小时以后。
		riskItemRequest.setDelivery_cycle("other");

		String provinceCode = queryProvinceCityCode(order.getProvince(), true);
		String cityCode = queryProvinceCityCode(order.getCity(), false);
		log.info("provinceCode:{}, cityCode:{}", provinceCode, cityCode);
		riskItemRequest.setDelivery_addr_province(provinceCode);
		riskItemRequest.setDelivery_addr_city(cityCode);
//		riskItemRequest.setDelivery_addr_full();
//		riskItemRequest.setDelivery_addr_district();
//		riskItemRequest.setDelivery_addr_street();
//		riskItemRequest.setDelivery_mail();
		payRequest.setRisk_item(JSONObject.toJSONString(riskItemRequest));

		// 终端用户IP。支持IPV4和IPV6两种格式的IP地址。
		// 正式环境传用户真实的IP
		payRequest.setClient_ip(ip);
		// 银行编码。付款方式为网银类时可指定。
		//params.setBankcode("01040000");

		// 付款方信息payerInfo
		PayerInfoRequest payerInfoRequest = new PayerInfoRequest();
		payerInfoRequest.setPayer_type("USER");
		payerInfoRequest.setPayer_id(order.getUid() == null ? null : String.valueOf(order.getUid()));
//		payerInfoRequest.setPassword();
//		payerInfoRequest.setRandom_key();

		payRequest.setPayerInfo(payerInfoRequest);

		// 付款方式信息payMethods
		List<PayMethodsRequest> payMethodsRequestList = new ArrayList<>();

		PayMethodsRequest payMethodsRequest = new PayMethodsRequest();
		payMethodsRequest.setMethod("WECHAT_APP_WXA");
		payMethodsRequest.setAmount(order.getPayPrice());

		payMethodsRequestList.add(payMethodsRequest);
		payRequest.setPayMethods(payMethodsRequestList);

		return payRequest;
    }

	/**
	 * 获取省市编码
	 *
	 * @param
	 */
	private String queryProvinceCityCode(String address, boolean isProvince) {
		log.info("省市编码 address:{}", address);

		if(StringUtils.isEmpty(address)){
			return null;
		}
		JSONArray jsonArray = null;
		try {
			// json列表查询的
			jsonArray = QueryCityItem.getMethodConfig();
		} catch (Exception e) {
			log.error("获取省市编码异常:{}", e.fillInStackTrace());
			throw new CrmebException("获取省市编码异常");
		}
		log.info("省市编码 jsonArray:{}", jsonArray.toString());

		List<ProvinceCityItemVo> itemDtoList = JSON.parseArray(jsonArray.toString(), ProvinceCityItemVo.class);

		for(ProvinceCityItemVo provinceCityItemVo : itemDtoList){
			if(isProvince) {
				if (provinceCityItemVo.getRegion() != null && provinceCityItemVo.getRegion().contains(address)) {
					return provinceCityItemVo.getCode();
				}
			}else {
				List<CityItemVo> cityItemVoList = provinceCityItemVo.getRegionEntitys();
				if (CollectionUtils.isEmpty(cityItemVoList)) {
					continue;
				}
				for (CityItemVo cityItemVo : cityItemVoList) {
					if (cityItemVo.getRegion() != null && cityItemVo.getRegion().contains(address)) {
						return cityItemVo.getCode();
					}
				}
			}
		}
		return null;
	}

	/**
	 * 基础参数组装
	 * @author daigb
	 * @date:  2022-07-18 15:29
	 */
	private LianlianOrderRequest getOrderParams(StoreOrder order, Integer merId) {
		LianlianOrderRequest payRequest = new LianlianOrderRequest();

		// 回调地址
		// TODO lianlian
		String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
		String domainUrl = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN_URL);

		String timestamp = LLianPayDateUtils.getTimestamp();
		Integer user_id = order.getUid();



		payRequest.setTimestamp(timestamp);
		// TODO OID_PARTNER_TEST
		payRequest.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
		payRequest.setTxn_type(Constants.TXN_TYPE);
		payRequest.setUser_id(user_id == null ? null : String.valueOf(user_id));
		// 用户类型。默认：注册用户。匿名用户：ANONYMOUS
		payRequest.setUser_type("ANONYMOUS");
		// TODO 交易结果异步通知接收地址，建议HTTPS协议
		payRequest.setNotify_url(domain + WeChatConstants.PAY_NOTIFY_API_URI_LIANLIAN_DEGREE);
		// TODO 交易返回地址，支付结果页面返回地址。
		payRequest.setReturn_url(domainUrl + WeChatConstants.PAY_NOTIFY_API_URI_LIANLIAN_DEGREE_PAGE);

//		payRequest.setPay_expire();

		// 商户订单信息
		OrderInfoRequest orderInfoRequest = new OrderInfoRequest();
		orderInfoRequest.setTxn_seqno(order.getOrderId());
		orderInfoRequest.setTxn_time(timestamp);
		orderInfoRequest.setTotal_amount(order.getPayPrice());
//		orderInfoRequest.setFee_amount();
//		orderInfoRequest.setOrder_info();
//		orderInfoRequest.setGoods_name();
//		orderInfoRequest.setGoods_url();
//		orderInfoRequest.setCoupon_pay_mode("CONSUME_SUCCESS_PAY");

		payRequest.setOrderInfo(orderInfoRequest);

		// 门店信息详情
//		StoreInfoRequest storeInfoRequest = new StoreInfoRequest();
//		storeInfoRequest.setStore_id();
//		storeInfoRequest.setStore_name();
//
//		payRequest.setStore_info(storeInfoRequest);

		// 收款方信息
		List<PayeeInfoRequest> payeeInfoRequestList = new ArrayList<>();
		PayeeInfoRequest payeeInfoRequest = new PayeeInfoRequest();
		payeeInfoRequest.setPayee_id(Constants.OID_PARTNER_PROD_TUGOU);
		payeeInfoRequest.setPayee_type("MERCHANT");
//		payeeInfoRequest.setPayee_accttype();
		payeeInfoRequest.setPayee_amount(order.getPayPrice().toString());
//		payeeInfoRequest.setPayee_memo();

		payeeInfoRequestList.add(payeeInfoRequest);
		payRequest.setPayeeInfo(payeeInfoRequestList);

		return payRequest;
	}

	/**
	 * orderAmt=freightAmt+goodsAmt+taxAmt-offsetAmt
	 * 支付单海关申报
	 * @author daigb
	 * @date:  2022-08-01 13:45
	 */
	public CustomsPushPayResponse payCustoms(Integer merId, String realName, String idCard, String orderInfoId,
									 String childOrderNumber, BigDecimal orderAmt, BigDecimal freightAmt, BigDecimal goodsAmt,
									 BigDecimal taxAmt, BigDecimal offsetAmt, Date payTime, boolean sub_order_flag) {
		String domain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN);
		String timestamp = LLianPayDateUtils.getTimestamp();
		CustomsPushPayRequest pushPayRequest = new CustomsPushPayRequest();
		pushPayRequest.setTimestamp(timestamp);
		pushPayRequest.setUsername(realName);
		pushPayRequest.setId_type("ID_CARD");
		pushPayRequest.setId_no(idCard);
		// TODO
		pushPayRequest.setTxn_seqno(childOrderNumber);
		// TODO
		pushPayRequest.setOrg_txn_seqno(orderInfoId);
		pushPayRequest.setTxn_time(DateUtil.dateToStr(payTime, Constants.DATE_TIME_FORMAT_NUM));
//		pushPayRequest.setOperate_type("ADD");
		pushPayRequest.setTotal_amount(orderAmt);

		// TODO DIDIOK 支付
		pushPayRequest.setNotify_url(domain + WeChatConstants.PAY_NOTIFY_API_URI_LIANLIAN_DEGREE_CUSTOMS); // 回调地址
		// TODO 这里暂时写死为 兔购（温喵街-现为兔购跨境）
		/*if (merId == 78 || merId == 30){
			}*/
		pushPayRequest.setOid_partner(Constants.OID_PARTNER_PROD_TUGOU);
		pushPayRequest.setPlatform_code("3303960EZ4"); // 商户海关备案号
		pushPayRequest.setPlatform_name("浙江速云供应链科技有限公司"); // 海关公司名

		// TODO 杭州海关代码
		pushPayRequest.setCustom_code("300108");
		if(sub_order_flag) {
			pushPayRequest.setSub_order_flag("Y"); // 拆单标识。拆单场景下，送固定值Y，标识该笔支付单需要拆单推送
		}
		pushPayRequest.setPay_gds_amt(goodsAmt); // 物流费
		pushPayRequest.setPay_fee_amount(freightAmt); // 物流费
		pushPayRequest.setPay_tax_amt(taxAmt); // 税款
		log.info("--------------- 连连聚合支付报关入参: {}", JSON.toJSONString(pushPayRequest));
		LLianPayClient lLianPayClient = new LLianPayClient();
		String result = lLianPayClient.sendRequest(Constants.CUSTOMS_PUSH_PAY_URL_PROD, JSON.toJSONString(pushPayRequest));
		log.info("--------------- 连连聚合支付报关返回结果源数据: {}", JSON.toJSONString(result));
		DingTalkMsgUtil.sendMsg(DingMsgEnum.OTHER,"连连聚合支付报关返回结果:"+JSON.toJSONString(result));

		// 下单结果
		CustomsPushPayResponse response = JSONObject.parseObject(result, CustomsPushPayResponse.class);

		return response;
	}

}
